#ifndef _UTILEX_THREADPOOL_HPP_
#define _UTILEX_THREADPOOL_HPP_

#include <crt_util.h>

#ifdef __cplusplus

class CThreadPool : private CThread
{
public:
    CThreadPool() { s_memset(&pool, 0, sizeof(_threadpool_t)); }
    virtual ~CThreadPool() { s_memset(&pool, 0, sizeof(_threadpool_t)); }
    static int workfunccb(void* data, void* ctx)
    {
        _threadpool_t* parent_context = static_cast<_threadpool_t*>(data);
        rc_error(parent_context != NULL, S_ERROR);

        CThreadPool* pool = static_cast<CThreadPool*>(parent_context->ctx);
        rc_error(pool != NULL, S_ERROR);

        pool->ThreadPool_Run(data, ctx);

        return S_SUCCESS;
    }

    static int startfunccb(void* data, void* ctx)
    {
        _threadpool_t* parent_context = static_cast<_threadpool_t*>(data);
        rc_error(parent_context != NULL, S_ERROR);

        CThreadPool* pool = static_cast<CThreadPool*>(parent_context->ctx);
        rc_error(pool != NULL, S_ERROR);

        pool->ThreadPool_Start();

        return S_SUCCESS;
    }
    static int stopfunccb(void* data, void* ctx)
    {
        _threadpool_t* parent_context = static_cast<_threadpool_t*>(data);
        rc_error(parent_context != NULL, S_ERROR);

        CThreadPool* pool = static_cast<CThreadPool*>(parent_context->ctx);
        rc_error(pool != NULL, S_ERROR);

        pool->ThreadPool_Stop();
        return S_SUCCESS;
    }

    static int errorfunccb(void* data, void* ctx) { return S_SUCCESS; }

    int StartThreadPool(int count)
    {
        pool.count = count;
        pool.ctx = this;
        pool.func.start = CThreadPool::startfunccb;
        pool.func.work = CThreadPool::workfunccb;
        pool.func.stop = CThreadPool::stopfunccb;
        pool.func.error = CThreadPool::errorfunccb;
        init_threadpool(&pool);

        return CThread::Start_Thread();
    }

    int StopThreadPool()
    {
        stop_threadpool(&pool);
        return CThread::Stop_Thread();
    }

    std_method(Thread_Init)() { return S_OK; }
    std_method(Thread_Run)()
    {
        start_threadpool(&pool);
        return S_OK;
    }
    std_method(Thread_UnInit)() { return S_OK; }

protected:
    std_method(ThreadPool_Run)(void* user, void* ctx) PURE;
    std_method(ThreadPool_Start)() PURE;
    std_method(ThreadPool_Stop)() PURE;
    std_method(ThreadPool_Error)() PURE;

private:
    int count;
    _threadpool_t pool;
};

#endif

#endif
